package br.com.winesys.geta.editor;

import java.awt.Font;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JFileChooser;
import javax.swing.JFormattedTextField;
import javax.swing.JFormattedTextField.AbstractFormatterFactory;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.filechooser.FileFilter;
import org.jdesktop.swingx.JXTitledSeparator;
import br.com.winesys.geta.databinding.Field;
import br.com.winesys.geta.databinding.component.Hidden;
import br.com.winesys.geta.databinding.component.editor.BigDecimalEditor;
import br.com.winesys.geta.databinding.component.editor.CharacterTextField;
import br.com.winesys.geta.databinding.component.editor.DoubleEditor;
import br.com.winesys.geta.databinding.component.editor.FloatEditor;
import br.com.winesys.geta.databinding.component.editor.IntegerEditor;
import br.com.winesys.geta.databinding.component.editor.LimitedTextArea;
import br.com.winesys.geta.databinding.component.editor.LimitedTextField;
import br.com.winesys.geta.databinding.component.editor.LongEditor;
import br.com.winesys.geta.databinding.component.editor.PasswordEditor;
import br.com.winesys.geta.databinding.component.selector.EnumSelector;
import br.com.winesys.geta.databinding.component.selector.FileSelector;
import br.com.winesys.geta.databinding.component.selector.FolderSelector;
import br.com.winesys.geta.databinding.component.selector.ObjectSelector;
import br.com.winesys.geta.databinding.component.table.ListSelector;
import br.com.winesys.geta.databinding.component.table.TableEditor;
import br.com.winesys.geta.databinding.component.table.TableModel;
import com.toedter.calendar.JDateChooser;

public final class FieldFactory {

	private FieldFactory() {
	}

	public static Field createCustomComponent(String property, String displayName, JComponent editor, Object labelLayoutData, Object layoutData) {
		editor.putClientProperty(Field.LAYOUT, layoutData);
		editor.putClientProperty(Field.LABEL_LAYOUT, labelLayoutData);
		return new Field(property, displayName, editor);
	}

	public static Field createText(String text, Object labelLayoutData) {
		JLabel label = new JLabel(text);
		label.putClientProperty(Field.LAYOUT, labelLayoutData);
		return new Field(null, null, label);
	}

	public static Field createSeparator(String text, Object labelLayoutData) {
//		JXTitledSeparator label = new JXTitledSeparator(text);
		JLabel label = new JLabel(text);
		label.setFont(new Font(label.getFont().getName(), Font.BOLD, label.getFont().getSize()));
		label.putClientProperty(Field.LAYOUT, labelLayoutData);
		return new Field(null, null, label);
	}

	public static Field createReadOnlyStringProperty(String property, String displayName, int columns, Object labelLayoutData, Object layoutData) {
		JTextField editor = new JTextField();
		editor.setColumns(columns);
		editor.setEditable(false);
		editor.setFocusable(false);
		editor.putClientProperty(Field.LABEL_LAYOUT, labelLayoutData);
		editor.putClientProperty(Field.LAYOUT, layoutData);
		return new Field(property, displayName, editor);
	}

	public static Field createStringProperty(String property, String displayName, int limit, int columns, Object labelLayoutData, Object layoutData) {
		LimitedTextField editor = new LimitedTextField();
		editor.setColumns(columns);
		editor.setLimit(limit);
		editor.putClientProperty(Field.LABEL_LAYOUT, labelLayoutData);
		editor.putClientProperty(Field.LAYOUT, layoutData);
		return new Field(property, displayName, editor);
	}

	public static Field createReadOnlyCharacterProperty(String property, String displayName, Object labelLayoutData, Object layoutData) {
		CharacterTextField editor = new CharacterTextField();
		editor.setEditable(false);
		editor.setFocusable(false);
		editor.putClientProperty(Field.LABEL_LAYOUT, labelLayoutData);
		editor.putClientProperty(Field.LAYOUT, layoutData);
		return new Field(property, displayName, editor);
	}

	public static Field createCharacterProperty(String property, String displayName, Object labelLayoutData, Object layoutData) {
		CharacterTextField editor = new CharacterTextField();
		editor.setColumns(1);
		editor.putClientProperty(Field.LABEL_LAYOUT, labelLayoutData);
		editor.putClientProperty(Field.LAYOUT, layoutData);
		return new Field(property, displayName, editor);
	}

	public static Field createReadOnlyMultiLineStringProperty(String property, String displayName, int columns, int rows, Object labelLayoutData, Object layoutData) {
		LimitedTextArea editor = new LimitedTextArea();
		JScrollPane scrollPane = new JScrollPane(editor);
		editor.putClientProperty("scroll", scrollPane);
		editor.setColumns(columns);
		editor.setRows(rows);
		editor.setEditable(false);
		editor.setFocusable(false);
		editor.putClientProperty(Field.LABEL_LAYOUT, labelLayoutData);
		editor.putClientProperty(Field.LAYOUT, layoutData);
		return new Field(property, displayName, editor);
	}

	public static Field createMultiLineStringProperty(String property, String displayName, int limit, int columns, int rows, Object labelLayoutData, Object layoutData) {
		LimitedTextArea editor = new LimitedTextArea();
		JScrollPane scrollPane = new JScrollPane(editor);
		editor.putClientProperty(Field.SCROLL, scrollPane);
		editor.setColumns(columns);
		editor.setRows(rows);
		editor.setLimit(limit);
		editor.putClientProperty(Field.LABEL_LAYOUT, labelLayoutData);
		editor.putClientProperty(Field.LAYOUT, layoutData);
		return new Field(property, displayName, editor);
	}

	public static Field createReadOnlyPasswordProperty(String property, String displayName, int columns, Object labelLayoutData, Object layoutData) {
		PasswordEditor editor = new PasswordEditor();
		editor.setColumns(columns);
		editor.setEnabled(false);
		editor.setFocusable(false);
		editor.putClientProperty(Field.LABEL_LAYOUT, labelLayoutData);
		editor.putClientProperty(Field.LAYOUT, layoutData);
		return new Field(property, displayName, editor);
	}

	public static Field createPasswordProperty(String property, String displayName, int limit, int columns, Object labelLayoutData, Object layoutData) {
		PasswordEditor editor = new PasswordEditor();
		editor.setColumns(columns);
		editor.setLimit(limit);
		editor.putClientProperty(Field.LABEL_LAYOUT, labelLayoutData);
		editor.putClientProperty(Field.LAYOUT, layoutData);
		return new Field(property, displayName, editor);
	}

	public static Field createReadOnlyLongProperty(String property, String displayName, int columns, Object labelLayoutData, Object layoutData) {
		LongEditor editor = new LongEditor();
		editor.setColumns(columns);
		editor.setEnabled(false);
		editor.setFocusable(false);
		editor.putClientProperty(Field.LABEL_LAYOUT, labelLayoutData);
		editor.putClientProperty(Field.LAYOUT, layoutData);
		return new Field(property, displayName, editor);
	}

	public static Field createLongProperty(String property, String displayName, int columns, Object labelLayoutData, Object layoutData) {
		LongEditor editor = new LongEditor();
		editor.setColumns(columns);
		editor.putClientProperty(Field.LABEL_LAYOUT, labelLayoutData);
		editor.putClientProperty(Field.LAYOUT, layoutData);
		return new Field(property, displayName, editor);

	}

	public static Field createReadOnlyIntegerProperty(String property, String displayName, int columns, Object labelLayoutData, Object layoutData) {
		IntegerEditor editor = new IntegerEditor();
		editor.setColumns(columns);
		editor.setEditable(false);
		editor.setFocusable(false);
		editor.putClientProperty(Field.LABEL_LAYOUT, labelLayoutData);
		editor.putClientProperty(Field.LAYOUT, layoutData);
		return new Field(property, displayName, editor);
	}

	public static Field createIntegerProperty(String property, String displayName, int columns, Object labelLayoutData, Object layoutData) {
		IntegerEditor editor = new IntegerEditor();
		editor.setColumns(columns);
		editor.putClientProperty(Field.LABEL_LAYOUT, labelLayoutData);
		editor.putClientProperty(Field.LAYOUT, layoutData);
		return new Field(property, displayName, editor);
	}

	public static Field createReadOnlyFloatProperty(String property, String displayName, String format, int columns, Object labelLayoutData, Object layoutData) {
		FloatEditor editor = new FloatEditor();
		editor.setColumns(columns);
		editor.setFormat(format);
		editor.setEditable(false);
		editor.setFocusable(false);
		editor.putClientProperty(Field.LABEL_LAYOUT, labelLayoutData);
		editor.putClientProperty(Field.LAYOUT, layoutData);
		return new Field(property, displayName, editor);
	}

	public static Field createFloatProperty(String property, String displayName, String format, int columns, Object labelLayoutData, Object layoutData) {
		FloatEditor editor = new FloatEditor();
		editor.setColumns(columns);
		editor.setFormat(format);
		editor.putClientProperty(Field.LABEL_LAYOUT, labelLayoutData);
		editor.putClientProperty(Field.LAYOUT, layoutData);
		return new Field(property, displayName, editor);
	}

	public static Field createReadOnlyDoubleProperty(String property, String displayName, String format, int columns, Object labelLayoutData, Object layoutData) {
		DoubleEditor editor = new DoubleEditor();
		editor.setColumns(columns);
		editor.setFormat(format);
		editor.setEditable(false);
		editor.setFocusable(false);
		editor.putClientProperty(Field.LABEL_LAYOUT, labelLayoutData);
		editor.putClientProperty(Field.LAYOUT, layoutData);
		return new Field(property, displayName, editor);
	}

	public static Field createDoubleProperty(String property, String displayName, String format, int columns, Object labelLayoutData, Object layoutData) {
		DoubleEditor editor = new DoubleEditor();
		editor.setColumns(columns);
		editor.setFormat(format);
		editor.putClientProperty(Field.LABEL_LAYOUT, labelLayoutData);
		editor.putClientProperty(Field.LAYOUT, layoutData);
		return new Field(property, displayName, editor);
	}

	public static Field createReadOnlyBigDecimalProperty(String property, String displayName, String format, int columns, Object labelLayoutData, Object layoutData) {
		BigDecimalEditor editor = new BigDecimalEditor();
		editor.setColumns(columns);
		editor.setFormat(format);
		editor.setEditable(false);
		editor.setFocusable(false);
		editor.putClientProperty(Field.LABEL_LAYOUT, labelLayoutData);
		editor.putClientProperty(Field.LAYOUT, layoutData);
		return new Field(property, displayName, editor);
	}

	public static Field createBigDecimalProperty(String property, String displayName, String format, int columns, Object labelLayoutData, Object layoutData) {
		BigDecimalEditor editor = new BigDecimalEditor();
		editor.setColumns(columns);
		editor.setFormat(format);
		editor.putClientProperty(Field.LABEL_LAYOUT, labelLayoutData);
		editor.putClientProperty(Field.LAYOUT, layoutData);
		return new Field(property, displayName, editor);
	}

	public static Field createReadOnlyDateProperty(String property, String displayName, String pattern, Object labelLayoutData, Object layoutData) {
		JDateChooser editor = new JDateChooser(pattern, pattern, '_');
		editor.setEnabled(false);
		editor.setFocusable(false);
		editor.putClientProperty(Field.LABEL_LAYOUT, labelLayoutData);
		editor.putClientProperty(Field.LAYOUT, layoutData);
		return new Field(property, displayName, editor);
	}

	public static Field createDateProperty(String property, String displayName, String pattern, Object labelLayoutData, Object layoutData) {
		JDateChooser editor;
		if (pattern.isEmpty()) {
			editor = new JDateChooser();
		} else {
			editor = new JDateChooser(pattern, pattern, '_');
		}
		editor.putClientProperty(Field.LABEL_LAYOUT, labelLayoutData);
		editor.putClientProperty(Field.LAYOUT, layoutData);
		return new Field(property, displayName, editor);
	}

	public static Field createReadOnlyFormattedStringProperty(String property, String displayName, AbstractFormatterFactory formatterFactory, int columns, Object labelLayoutData, Object layoutData) {
		JFormattedTextField editor = new JFormattedTextField(formatterFactory);
		editor.setColumns(columns);
		editor.setEditable(false);
		editor.setFocusable(false);
		editor.putClientProperty(Field.LABEL_LAYOUT, labelLayoutData);
		editor.putClientProperty(Field.LAYOUT, layoutData);
		return new Field(property, displayName, editor);
	}

	public static Field createFormattedStringProperty(String property, String displayName, AbstractFormatterFactory formatterFactory, int columns, Object labelLayoutData, Object layoutData) {
		JFormattedTextField editor = new JFormattedTextField(formatterFactory);
		editor.setColumns(columns);
		editor.putClientProperty(Field.LABEL_LAYOUT, labelLayoutData);
		editor.putClientProperty(Field.LAYOUT, layoutData);
		return new Field(property, displayName, editor);
	}

	public static Field createReadOnlyBooleanProperty(String property, String displayName, Object layoutData) {
		JCheckBox editor = new JCheckBox(displayName);
		editor.setEnabled(false);
		editor.setFocusable(false);
		editor.putClientProperty(Field.LAYOUT, layoutData);
		return new Field(property, null, editor);
	}

	public static Field createBooleanProperty(String property, String displayName, Object layoutData) {
		JCheckBox editor = new JCheckBox(displayName);
		editor.putClientProperty(Field.LAYOUT, layoutData);
		return new Field(property, null, editor);
	}

	public static <T extends Enum<?>> Field createReadOnlyEnumProperty(String property, String displayName, T[] values, Object labelLayoutData, Object layoutData) {
		EnumSelector<T> editor = new EnumSelector<T>();
		editor.setValues(values);
		editor.setEnabled(false);
		editor.setFocusable(false);
		editor.putClientProperty(Field.LABEL_LAYOUT, labelLayoutData);
		editor.putClientProperty(Field.LAYOUT, layoutData);
		return new Field(property, displayName, editor);
	}

	public static <T extends Enum<?>> Field createEnumProperty(String property, String displayName, T[] values, Object labelLayoutData, Object layoutData) {
		EnumSelector<T> editor = new EnumSelector<T>();
		editor.setValues(values);
		editor.putClientProperty(Field.LABEL_LAYOUT, labelLayoutData);
		editor.putClientProperty(Field.LAYOUT, layoutData);
		return new Field(property, displayName, editor);
	}

	public static <T> Field createListProperty(String property, String displayName, T[] values, Object labelLayoutData, Object layoutData) {
		ListSelector<T> editor = new ListSelector<T>();
		editor.setValues(values);
		editor.putClientProperty(Field.LABEL_LAYOUT, labelLayoutData);
		editor.putClientProperty(Field.LAYOUT, layoutData);
		return new Field(property, displayName, editor);
	}

	public static <Entity> Field createTableProperty(String property, TableModel<Entity> tableModel, Editor<Entity> objectEditor, Class<Entity> itemClass, Object layoutData) {
		TableEditor<Entity> editor = new TableEditor<Entity>(tableModel, objectEditor, itemClass);
		editor.putClientProperty(Field.LAYOUT, layoutData);
		return new Field(property, null, editor);
	}

	public static Field createReadOnlyComboProperty(String property, String displayName, Object[] values, Object labelLayoutData, Object layoutData) {
		JComboBox editor = new JComboBox(values);
		editor.setEditable(false);
		editor.setFocusable(false);
		editor.putClientProperty(Field.LABEL_LAYOUT, labelLayoutData);
		editor.putClientProperty(Field.LAYOUT, layoutData);
		return new Field(property, displayName, editor);
	}

	public static Field createNullComboProperty(String property, String displayName, Object[] values, Object labelLayoutData, Object layoutData) {
		JComboBox editor = new JComboBox();
		editor.addItem(null);
		for (Object obj : values) {
			editor.addItem(obj);
		}
		editor.setEditable(false);
		editor.putClientProperty(Field.LABEL_LAYOUT, labelLayoutData);
		editor.putClientProperty(Field.LAYOUT, layoutData);
		return new Field(property, displayName, editor);
	}

	public static Field createComboProperty(String property, String displayName, Object[] values, Object labelLayoutData, Object layoutData) {
		JComboBox editor = new JComboBox(values);
		editor.setEditable(false);
		editor.putClientProperty(Field.LABEL_LAYOUT, labelLayoutData);
		editor.putClientProperty(Field.LAYOUT, layoutData);
		return new Field(property, displayName, editor);
	}

	public static Field createReadOnlyObjectProperty(String property, String displayName, ObjectSelector<?> editor, Object labelLayoutData, Object layoutData) {
		editor.setEnabled(false);
		editor.setFocusable(false);
		editor.putClientProperty(Field.LABEL_LAYOUT, labelLayoutData);
		editor.putClientProperty(Field.LAYOUT, layoutData);
		return new Field(property, displayName, editor);
	}

	public static Field createObjectProperty(String property, String displayName, ObjectSelector<?> editor, Object labelLayoutData, Object layoutData) {
		editor.putClientProperty(Field.LABEL_LAYOUT, labelLayoutData);
		editor.putClientProperty(Field.LAYOUT, layoutData);
		return new Field(property, displayName, editor);
	}

	public static Field createFileSaveProperty(String property, String displayName, FileFilter filter, Object labelLayoutData, Object layoutData) {
		FileSelector editor = new FileSelector(JFileChooser.SAVE_DIALOG, filter);
		editor.putClientProperty(Field.LABEL_LAYOUT, labelLayoutData);
		editor.putClientProperty(Field.LAYOUT, layoutData);
		return new Field(property, displayName, editor);
	}

	public static Field createFileOpenProperty(String property, String displayName, FileFilter filter, Object labelLayoutData, Object layoutData) {
		FileSelector editor = new FileSelector(JFileChooser.OPEN_DIALOG, filter);
		editor.putClientProperty(Field.LABEL_LAYOUT, labelLayoutData);
		editor.putClientProperty(Field.LAYOUT, layoutData);
		return new Field(property, displayName, editor);
	}

	public static Field createFolderProperty(String property, String displayName, int dialogType, Object labelLayoutData, Object layoutData) {
		FolderSelector editor = new FolderSelector(dialogType);
		editor.putClientProperty(Field.LABEL_LAYOUT, labelLayoutData);
		editor.putClientProperty(Field.LAYOUT, layoutData);
		return new Field(property, displayName, editor);
	}

	public static Field createHiddenProperty(String property, Object value) {
		Hidden editor = new Hidden(value);
		return new Field(property, null, editor);
	}

	public static Field createComponent(String property, JComponent component, Object layoutData) {
		component.putClientProperty(Field.LAYOUT, layoutData);
		return new Field(property, null, component);
	}
}